#ifndef __CLINESEGMENT2D_H__
#define __CLINESEGMENT2D_H__

#include "StdDefs.h"
#include "CMathFixed.h"
#include "CVector2d.h"
#include "CSpace.h"


// CLineSegment2d* must maintain casting ability with (fixed*).
// CLineSegment2d may not have virtuals, inherited, or instantiated data.
 

class CLineSegment2d
{
public:
	CLineSegment2d(){}
	CLineSegment2d( const fixed* ij );
	CLineSegment2d( fixed v0i, fixed v0j, fixed v1i, fixed v1j );
	CLineSegment2d( const CVector2d* v );
	CLineSegment2d( const CVector2d& v0, const CVector2d& v1 ); 
	~CLineSegment2d(){}

	static CSpace::Relativity	DetermineSpace( const CVector2d& v0, const CVector2d& v1,
												const CVector2d& point );

	static fixed				ClosestPoint( const CVector2d& v0, const CVector2d& v1,
											  const CVector2d& point, CVector2d& closestPoint );

	static CVector2d&			ShortestVectorToPoint( const CVector2d& v0, const CVector2d& v1,
													   const CVector2d& point,
													   CVector2d& v, fixed& u );

	static void					ShortestVectorToSegment( const CVector2d& seg0V0, const CVector2d& seg0V1,
														 const CVector2d& seg1V0, const CVector2d& seg1V1,
														 CVector2d& c1, CVector2d& c2, fixed* u0 = NULL, fixed *u1 = NULL );


	static void					ComputeVertexNormal( const CVector2d& vtx0, const CVector2d& vtx1,
													 const CVector2d& vtx2,
													 CVector2d& vtxNormal,
													 CSpace::Relativity relativity = CSpace::Outside );

	static boolean				Intersects( const CVector2d& seg0V0, const CVector2d& seg0V1,
											const CVector2d& seg1V0, const CVector2d& seg1V1,
											fixed* u0, fixed *u1 );

	static void					ExtractSuccessiveVertices( CVector2d* vtx, int32 nOfVerticesInClosedGraph, 
														   int32 idxOfFirst, 
														   CVector2d** v0, CVector2d** v1, CVector2d** v2 = NULL );

	CLineSegment2d&				Set( const CVector2d& v0, const CVector2d& v1 );

	CSpace::Relativity			DetermineSpace( const CVector2d& point ) const;

	fixed						ClosestPoint( const CVector2d& point, CVector2d& closestPoint ) const;

	CVector2d&					ShortestVectorToPoint( const CVector2d& point, 
													   CVector2d& v, fixed& u ) const;

	void						ShortestVectorToSegment( const CLineSegment2d& s2, CVector2d& c1, CVector2d& c2, fixed* u0 = NULL, fixed *u1 = NULL ) const;

	boolean						Intersects( const CLineSegment2d& seg, fixed* uThis, fixed *uSeg ) const;


	CLineSegment2d&				operator=( const fixed* ij ); 
	CLineSegment2d&				operator=( const CVector2d* v );

	fixed&						operator[]( uint32 idx );

	CVector2d					m_v0;
	CVector2d					m_v1;
};




inline 
CLineSegment2d::CLineSegment2d( const fixed* ij )
{ 
	m_v0.m_i = *ij; 
	m_v0.m_j = *( ij + 1 );
	m_v1.m_i = *( ij + 2 ); 
	m_v1.m_j = *( ij + 3 );
}


inline
CLineSegment2d::CLineSegment2d( fixed v0i, fixed v0j, fixed v1i, fixed v1j )
{ 
	m_v0.m_i = v0i; 
	m_v0.m_j = v0j;
	m_v1.m_i = v1i; 
	m_v1.m_j = v1j;
}


inline 
CLineSegment2d::CLineSegment2d( const CVector2d* v )
{ 
	m_v0 = *v; 
	m_v1 = *( v + 1 ); 
}


inline 
CLineSegment2d::CLineSegment2d( const CVector2d& v0, const CVector2d& v1 )
{ 
	m_v0 = v0; 
	m_v1 = v1; 
}


inline
CLineSegment2d&	CLineSegment2d::Set( const CVector2d& v0, const CVector2d& v1 )
{
	m_v0 = v0; 
	m_v1 = v1; 
	return *this;
}


inline
CSpace::Relativity CLineSegment2d::DetermineSpace( const CVector2d& point ) const
{
	return DetermineSpace( m_v0, m_v1, point );
}


inline
fixed CLineSegment2d::ClosestPoint( const CVector2d& point, CVector2d& closestPoint ) const
{
	return ClosestPoint( m_v0, m_v1, point, closestPoint );
}


inline
CVector2d& CLineSegment2d::ShortestVectorToPoint( const CVector2d& point,
												  CVector2d& v, fixed& u ) const
{
	return ShortestVectorToPoint( m_v0, m_v1, point, v, u );
}


inline
void CLineSegment2d::ShortestVectorToSegment( const CLineSegment2d& s2, CVector2d& c1, CVector2d& c2, fixed* u0, fixed *u1 ) const
{
	ShortestVectorToSegment( this->m_v0, this->m_v1, s2.m_v0, s2.m_v1, c1, c2, u0, u1 );
}

inline
boolean	CLineSegment2d::Intersects( const CLineSegment2d& seg, fixed* uThis, fixed *uSeg ) const
{
	return Intersects( m_v0, m_v1, seg.m_v0, seg.m_v1, uThis, uSeg );
}


inline
CLineSegment2d& CLineSegment2d::operator=( const fixed* ij )
{ 
	m_v0.m_i = *ij; 
	m_v0.m_j = *( ij + 1 );
	m_v1.m_i = *( ij + 2 ); 
	m_v1.m_j = *( ij + 3 );

	return *this;
}


inline
CLineSegment2d& CLineSegment2d::operator=( const CVector2d* v )
{ 
	m_v0 = *v; 
	m_v1 = *( v + 1 ); 
	return *this;
}


inline
fixed& CLineSegment2d::operator[]( uint32 idx )
{
	ASSERT( idx < 4 );

	return *( ( (fixed*)this ) + idx );
}


 

#endif // __CLINESEGMENT2D_H__